<?php 
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.1 / SVN信息: $Id: class.Stream.php 2166 2009-12-22 07:08:12Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

namespace JCAT\PDRL\MultiTask\Task ;


use JCAT\PDRL\MultiTask;

class Stream
{
    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function Setup($hHandle,MultiTask\StreamTasks $aTasks,$nStreamTypes)
    {
        foreach (array(MultiTask\StreamTasks::READ,MultiTask\StreamTasks::WRITE,MultiTask\StreamTasks::ERROR) as $nType)
        {
            if( !($nStreamTypes&$nType) )
            {
                continue ;
            }
            
    	    if( $this->arrHandles[$nType] )
    	    {
                $this->ExitTask($nType,false) ;
    	    }
    	    
    	    $aTasks->AddHandle( $nType,$hHandle,array($this,'OnStreamReady') ) ;
    	 
        	$this->arrHandles[$nType] = $hHandle ;
        	$this->arrTasks[$nType] = $aTasks ;
        }
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function ExitTask($nStreamTypes,$bCloseStream=false)
    {
        foreach (array(MultiTask\StreamTasks::READ,MultiTask\StreamTasks::WRITE,MultiTask\StreamTasks::ERROR) as $nType)
        {
            if( !($nStreamTypes&$nType) )
            {
                continue ;
            }
            if( !$this->arrHandles[$nType] or !$this->arrTasks[$nType] )
            {
                continue ;
            }
    	    
    	    $this->arrTasks[$nType]->RemoveHandle( $nType,$this->arrHandles[$nType] ) ;
        
        	// 关闭流
        	if($bCloseStream)
        	{
        	    fclose($this->arrHandles[$nType]) ;
        	}
        	
        	$this->arrHandles[$nType] = null ;
        	$this->arrTasks[$nType] = null ;
        }   	
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function OnStreamReady(MultiTask\IDispatch $aDispatch,MultiTask\StreamTasks $aTasks,$hHandle,$nType)
    {
    	if( $nType&MultiTask\StreamTasks::OUTPUT )
    	{
    	    $arrStat = stream_get_meta_data($hHandle) ;
    	    $nReadReadyBytes = intval($arrStat['unread_bytes']) ;
    	    if(!$nReadReadyBytes)
    	    {
    	        return ;
    	    }
    	    
	        $sOutput = fread($hHandle,$nReadReadyBytes) ;
    	    if($sOutput)
    	    {
    	        if( $nType&MultiTask\StreamTasks::READ )
    	        {
    	            $this->OnRead($sOutput,$aDispatch,$aTasks) ;
    	        }
    	        else if( $nType&MultiTask\StreamTasks::WRITE )
    	        {
    	            $this->OnError($sOutput,$aTasks,$aDispatch) ;
    	        }
    	    }
    	}
    	
    	else if( $nType&MultiTask\StreamTasks::INPUT )
    	{
    	    $sWriteBytes = $this->OnComposeWrite($aTasks,$aDispatch) ;
    	    
    	    if($sWriteBytes)
    	    {
    	        if(fwrite($hHandle,$sWriteBytes,strlen($sWriteBytes)))
    	        {
    	            $this->OnWrite($sWriteBytes,$aTasks,$aDispatch) ;
    	        }
    	    }
    	}
    }

    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function OnRead(&$sNewContent,MultiTask\StreamTasks $aTasks,MultiTask\IDispatch $aDispatch)
    {}
    
    /**
     * Description
     *
     * @access	public
     * @return	string
     */
    public function OnComposeWrite(MultiTask\StreamTasks $aTasks,MultiTask\IDispatch $aDispatch)
    {
    	return '' ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function OnWrite(&$sNewContent,MultiTask\StreamTasks $aTasks,MultiTask\IDispatch $aDispatch)
    {}
    
    /**
     * Description
     *
     * @access	public
     * @return	void
     */
    public function OnError(&$sNewErrMsg,MultiTask\StreamTasks $aTasks,MultiTask\IDispatch $aDispatch)
    {}
    
    
    /**
     * Description
     * 
     * @access	private
     * @var		int
     */
    private $nReadBytesOnce = 10240 ;
    
    /**
     * Description
     * 
     * @access	private
     * @var		array
     */
    private $arrHandles = array(
        MultiTask\StreamTasks::READ => null ,
        MultiTask\StreamTasks::WRITE => null ,
        MultiTask\StreamTasks::ERROR => null ,
    ) ;
    
    /**
     * Description
     * 
     * @access	private
     * @var		array
     */
    private $arrTasks = array(
        MultiTask\StreamTasks::READ => null ,
        MultiTask\StreamTasks::WRITE => null ,
        MultiTask\StreamTasks::ERROR => null ,
    ) ;
    
}

?>